package de.tudarmstadt.ukp.muip.fibqdojo.io.fibq;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Characters;
import javax.xml.stream.events.StartElement;
import javax.xml.transform.TransformerException;

import de.tudarmstadt.ukp.muip.fibqdojo.interfaces.IFIBQ;
import de.tudarmstadt.ukp.muip.fibqdojo.interfaces.IFIBQDistractor;
import de.tudarmstadt.ukp.muip.fibqdojo.io.Writer;

/**
 * Writes generated FIBQ's to an external file. The questions are written
 * token-separated in order to enable the decision whether the question shall be
 * reassembled as single string (e.g. Japanese) or separated (e.g. whitespace).
 * 
 * @author Tobias Horsmann
 */
public class FIBQWriter extends Writer implements FIBQ_Constants {

    public FIBQWriter(String path) throws ParserConfigurationException, FileNotFoundException, XMLStreamException {
        super(path, "UTF-8", " ");
    }

    public FIBQWriter(String path, String separator, String encoding) throws ParserConfigurationException,
            FileNotFoundException, XMLStreamException {
        super(path, encoding, separator);
    }

    public void process(List<IFIBQ> questions) throws ParserConfigurationException, TransformerException, IOException,
            XMLStreamException {
        for (IFIBQ question : questions) {
            processQuestion(question);
        }
    }

    private void processQuestion(IFIBQ question) throws XMLStreamException {

        StartElement sentStartElement = eventFactory.createStartElement("", "", FIBQ);
        eventWriter.add(sentStartElement);

        processSentence(question.getSentence());
        processDistractors(question.getDistractors());

        eventWriter.add(eventFactory.createEndElement("", "", FIBQ));
    }

    private void processDistractors(List<IFIBQDistractor> distractors) throws XMLStreamException {
        for (IFIBQDistractor distractor : distractors) {
            writeDistractor(distractor);
        }
    }

    private void processSentence(List<String> sentence) throws XMLStreamException {
        StartElement sentStartElement = eventFactory.createStartElement("", "", SENTENCE);
        eventWriter.add(sentStartElement);
        for (String token : sentence) {
            processToken(token);
        }
        eventWriter.add(eventFactory.createEndElement("", "", SENTENCE));
    }

    private void writeDistractor(IFIBQDistractor distractor) throws XMLStreamException {
        StartElement dis = eventFactory.createStartElement("", "", DISTRACTOR);
        eventWriter.add(dis);

        StartElement distractorValue = eventFactory.createStartElement("", "", DISTRACTOR_VALUE);
        eventWriter.add(distractorValue);
        Characters characters = eventFactory.createCharacters(distractor.getValue());
        eventWriter.add(characters);

        eventWriter.add(eventFactory.createEndElement("", "", DISTRACTOR_VALUE));

        if (distractor.isSolution()) {
            StartElement isSolEle = eventFactory.createStartElement("", "", ISSOLUTION);
            eventWriter.add(isSolEle);
            characters = eventFactory.createCharacters("true");
            eventWriter.add(characters);
            eventWriter.add(eventFactory.createEndElement("", "", ISSOLUTION));
        }
        eventWriter.add(eventFactory.createEndElement("", "", DISTRACTOR));
    }

    private void processToken(String token) throws XMLStreamException {
        StartElement sentStartElement = eventFactory.createStartElement("", "", TOKEN);
        eventWriter.add(sentStartElement);
        Characters characters = eventFactory.createCharacters(token);
        eventWriter.add(characters);
        eventWriter.add(eventFactory.createEndElement("", "", TOKEN));
    }
}
